package it.ipermemory.logic;

import java.io.IOException;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

/**
 * Allows you to parse an xml file containing Things. This class implements the
 * Singleton design pattern.
 * 
 * @author Gianluca Carlesso (gianluca.carlesso@gmail.com)
 * @version 1.0
 * 
 */
public class ThingsParserXML {
	/**
	 * Defines the tag that encloses a Thing in the xml file
	 */
	public final static String THING_TAG = "thing";

	/**
	 * Defines the tag that encloses a name of Thing in the xml file
	 */
	public final static String NAME = "name";

	/**
	 * Defines the tag that encloses a description of Thing in the xml file
	 */
	public final static String DESCRIPTION = "description";

	/**
	 * Defines the tag that encloses a sound of Thing in the xml file
	 */
	public final static String SOUND = "sound";

	/**
	 * Defines the tag that encloses a video of Thing in the xml file
	 */
	public final static String VIDEO = "video";

	/**
	 * Defines the tag that encloses a image of Thing in the xml file
	 */
	public final static String IMAGE = "image";

	/**
	 * Defines the tag that encloses a image compress of Thing in the xml file
	 */
	public final static String IMAGE_COMPRESS = "image_compress";

	/**
	 * Defines the tag that encloses a image full screen of Thing in the xml
	 * file
	 */
	public final static String IMAGE_FULL_SCREEN = "image_full_screen";

	/**
	 * Object containing the information retrieved from parsing
	 */
	private ArrayList<Thing> parsedData = null;

	/**
	 * Object that represents the parser instantiated for Singleton
	 */
	private static ThingsParserXML parser;

	/**
	 * Constructor that initializes the elements of the object. Made private.
	 */
	private ThingsParserXML() {
		parsedData = new ArrayList<Thing>();
	}

	/**
	 * The method parse the xml file passed to the parameter. Initialize the
	 * singleton and returns the instance.
	 * 
	 * @param xpp
	 *            object to parse
	 * @return object that represents the parser
	 * @throws XmlPullParserException
	 *             error in the parsing of the file
	 * @throws IOException
	 *             error in the parsing of the file
	 */
	public static synchronized ThingsParserXML parseXml(XmlPullParser xpp)
			throws XmlPullParserException, IOException {

		if (parser == null) {
			// If null I instantiate the object and parse
			parser = new ThingsParserXML();

			Thing thing = new Thing();
			int eventType = xpp.getEventType();

			// scan all tag of xml and switch case of tag name
			while (eventType != XmlPullParser.END_DOCUMENT) {
				if (eventType == XmlPullParser.START_TAG) {
					if (xpp.getName().equals(THING_TAG)) {
						thing.setId(Integer.valueOf(xpp.getAttributeValue(0)));
					} else if (xpp.getName().equals(NAME)) {
						thing.setName(valueTag(xpp));
					} else if (xpp.getName().equals(DESCRIPTION)) {
						thing.setDescription(valueTag(xpp));
					} else if (xpp.getName().equals(SOUND)) {
						thing.setSound(valueTag(xpp));
					} else if (xpp.getName().equals(VIDEO)) {
						thing.setVideo(valueTag(xpp));
					} else if (xpp.getName().equals(IMAGE)) {
						thing.setImage(valueTag(xpp));
					} else if (xpp.getName().equals(IMAGE_COMPRESS)) {
						thing.setImage_compress(valueTag(xpp));
					} else if (xpp.getName().equals(IMAGE_FULL_SCREEN)) {
						thing.setImage_full_screen(valueTag(xpp));
					}
				} else if (eventType == XmlPullParser.END_TAG
						&& xpp.getName().equals(THING_TAG)) {
					parser.parsedData.add(thing);
					thing = new Thing();
				}
				eventType = xpp.next();
			}
		}
		return parser;
	}

	/**
	 * Extract the value contained in a tag and returns it
	 * 
	 * @param xpp
	 *            object to parse
	 * @return the value of tag
	 * @throws XmlPullParserException
	 *             error in the parsing of the file
	 * @throws IOException
	 *             error in the parsing of the file
	 */
	private synchronized static String valueTag(XmlPullParser xpp)
			throws IOException, XmlPullParserException {
		// extract text of tag
		xpp.next();
		int eventType = xpp.getEventType();
		if (eventType == XmlPullParser.TEXT) {
			return xpp.getText();
		} else {
			throw new IOException();
		}
	}

	/**
	 * Return the object that contains data parsed
	 * 
	 * @return the object with data
	 */
	public synchronized ArrayList<Thing> getAllThings() {
		return parser.parsedData;
	}

	/**
	 * Returns the Thing corresponding to the id parameter passed to
	 * 
	 * @param id
	 *            identification Thing that you want to have in return
	 * @return Thing with all its data
	 */
	public synchronized Thing getThingById(final int id) {
		for (int i = 0; i < parser.parsedData.size(); i++) {
			if (parser.parsedData.get(i).getId() == id) {
				return parser.parsedData.get(i);
			}
		}
		return null;
	}
}
